﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using UIT.Converters;
using System.ComponentModel;
using System.Globalization;
using UIT.Utils;

namespace UIT._2D
{
    /// <summary>Describes the width, height, and location of a rectangle. </summary>
#if !SILVERLIGHT
    [ValueSerializer(typeof(RectValueSerializer))]
    [Serializable]
#endif
    [TypeConverter(typeof(RectConverter))]
    public struct Rect : IFormattable
    {
        internal double _x;
        internal double _y;
        internal double _width;
        internal double _height;
        private static readonly Rect s_empty = Rect.CreateEmptyRect();
        /// <summary>Gets a special value that represents a rectangle with no position or area. </summary>
        /// <returns>The empty rectangle, which has <see cref="P:System.Windows.Rect.X" /> and <see cref="P:System.Windows.Rect.Y" /> property values of <see cref="F:System.Double.PositiveInfinity" />, and has <see cref="P:System.Windows.Rect.Width" /> and <see cref="P:System.Windows.Rect.Height" /> property values of <see cref="F:System.Double.NegativeInfinity" />.</returns>
        public static Rect Empty
        {
            get
            {
                return Rect.s_empty;
            }
        }
        /// <summary>Gets a value that indicates whether the rectangle is the <see cref="P:System.Windows.Rect.Empty" /> rectangle.</summary>
        /// <returns>true if the rectangle is the <see cref="P:System.Windows.Rect.Empty" /> rectangle; otherwise, false.</returns>
        public bool IsEmpty
        {
            get
            {
                return this._width < 0.0;
            }
        }
        /// <summary>Gets or sets the position of the top-left corner of the rectangle.</summary>
        /// <returns>The position of the top-left corner of the rectangle. The default is (0, 0). </returns>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <see cref="P:System.Windows.Rect.Location" /> is set on an <see cref="P:System.Windows.Rect.Empty" /> rectangle. </exception>
        public Point Location
        {
            get
            {
                return new Point(this._x, this._y);
            }
            set
            {
                if (this.IsEmpty)
                {
                    throw new InvalidOperationException("CannotModifyEmptyRect");
                }
                this._x = value._x;
                this._y = value._y;
            }
        }
        /// <summary>Gets or sets the width and height of the rectangle. </summary>
        /// <returns>A <see cref="T:System.Windows.Size" /> structure that specifies the width and height of the rectangle.</returns>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <see cref="P:System.Windows.Rect.Size" /> is set on an <see cref="P:System.Windows.Rect.Empty" /> rectangle. </exception>
        public Size Size
        {
            get
            {
                if (this.IsEmpty)
                {
                    return Size.Empty;
                }
                return new Size(this._width, this._height);
            }
            set
            {
                if (value.IsEmpty)
                {
                    this = Rect.s_empty;
                    return;
                }
                if (this.IsEmpty)
                {
                    throw new InvalidOperationException("CannotModifyEmptyRect");
                }
                this._width = value._width;
                this._height = value._height;
            }
        }
        /// <summary>Gets or sets the x-axis value of the left side of the rectangle. </summary>
        /// <returns>The x-axis value of the left side of the rectangle.</returns>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <see cref="P:System.Windows.Rect.X" /> is set on an <see cref="P:System.Windows.Rect.Empty" /> rectangle. </exception>
        public double X
        {
            get
            {
                return this._x;
            }
            set
            {
                if (this.IsEmpty)
                {
                    throw new InvalidOperationException("CannotModifyEmptyRect");
                }
                this._x = value;
            }
        }
        /// <summary>Gets or sets the y-axis value of the top side of the rectangle. </summary>
        /// <returns>The y-axis value of the top side of the rectangle.</returns>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <see cref="P:System.Windows.Rect.Y" /> is set on an <see cref="P:System.Windows.Rect.Empty" /> rectangle. </exception>
        public double Y
        {
            get
            {
                return this._y;
            }
            set
            {
                if (this.IsEmpty)
                {
                }
                this._y = value;
            }
        }
        /// <summary>Gets or sets the width of the rectangle.  </summary>
        /// <returns>A positive number that represents the width of the rectangle. The default is 0.</returns>
        /// <exception cref="T:System.ArgumentException">
        ///   <see cref="P:System.Windows.Rect.Width" /> is set to a negative value.</exception>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <see cref="P:System.Windows.Rect.Width" /> is set on an <see cref="P:System.Windows.Rect.Empty" /> rectangle. </exception>
        public double Width
        {
            get
            {
                return this._width;
            }
            set
            {
                if (this.IsEmpty)
                {
                    throw new InvalidOperationException("CannotModifyEmptyRect");
                }
                if (value < 0.0)
                {
                    throw new ArgumentException("WidthCannotBeNegative");
                }
                this._width = value;
            }
        }
        /// <summary>Gets or sets the height of the rectangle. </summary>
        /// <returns>A positive number that represents the height of the rectangle. The default is 0.</returns>
        /// <exception cref="T:System.ArgumentException">
        ///   <see cref="P:System.Windows.Rect.Height" /> is set to a negative value.</exception>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <see cref="P:System.Windows.Rect.Height" /> is set on an <see cref="P:System.Windows.Rect.Empty" /> rectangle. </exception>
        public double Height
        {
            get
            {
                return this._height;
            }
            set
            {
                if (this.IsEmpty)
                {
                    throw new InvalidOperationException("CannotModifyEmptyRect");
                }
                if (value < 0.0)
                {
                    throw new ArgumentException("HeightCannotBeNegative");
                }
                this._height = value;
            }
        }
        /// <summary>Gets the x-axis value of the left side of the rectangle. </summary>
        /// <returns>The x-axis value of the left side of the rectangle.</returns>
        public double Left
        {
            get
            {
                return this._x;
            }
        }
        /// <summary>Gets the y-axis position of the top of the rectangle. </summary>
        /// <returns>The y-axis position of the top of the rectangle.</returns>
        public double Top
        {
            get
            {
                return this._y;
            }
        }
        /// <summary>Gets the x-axis value of the right side of the rectangle.  </summary>
        /// <returns>The x-axis value of the right side of the rectangle.</returns>
        public double Right
        {
            get
            {
                if (this.IsEmpty)
                {
                    return double.NegativeInfinity;
                }
                return this._x + this._width;
            }
        }
        /// <summary>Gets the y-axis value of the bottom of the rectangle. </summary>
        /// <returns>The y-axis value of the bottom of the rectangle. If the rectangle is empty, the value is <see cref="F:System.Double.NegativeInfinity" /> .</returns>
        public double Bottom
        {
            get
            {
                if (this.IsEmpty)
                {
                    return double.NegativeInfinity;
                }
                return this._y + this._height;
            }
        }
        /// <summary>Gets the position of the top-left corner of the rectangle. </summary>
        /// <returns>The position of the top-left corner of the rectangle.</returns>
        public Point TopLeft
        {
            get
            {
                return new Point(this.Left, this.Top);
            }
        }
        /// <summary>Gets the position of the top-right corner of the rectangle. </summary>
        /// <returns>The position of the top-right corner of the rectangle.</returns>
        public Point TopRight
        {
            get
            {
                return new Point(this.Right, this.Top);
            }
        }
        /// <summary>Gets the position of the bottom-left corner of the rectangle </summary>
        /// <returns>The position of the bottom-left corner of the rectangle.</returns>
        public Point BottomLeft
        {
            get
            {
                return new Point(this.Left, this.Bottom);
            }
        }
        /// <summary>Gets the position of the bottom-right corner of the rectangle. </summary>
        /// <returns>The position of the bottom-right corner of the rectangle.</returns>
        public Point BottomRight
        {
            get
            {
                return new Point(this.Right, this.Bottom);
            }
        }
        /// <summary>Compares two rectangles for exact equality.</summary>
        /// <returns>true if the rectangles have the same <see cref="P:System.Windows.Rect.Location" /> and <see cref="P:System.Windows.Rect.Size" /> values; otherwise, false.</returns>
        /// <param name="rect1">The first rectangle to compare.</param>
        /// <param name="rect2">The second rectangle to compare.</param>
        public static bool operator ==(Rect rect1, Rect rect2)
        {
            return rect1.X == rect2.X && rect1.Y == rect2.Y && rect1.Width == rect2.Width && rect1.Height == rect2.Height;
        }
        /// <summary>Compares two rectangles for inequality.  </summary>
        /// <returns>true if the rectangles do not have the same <see cref="P:System.Windows.Rect.Location" /> and <see cref="P:System.Windows.Rect.Size" /> values; otherwise, false.</returns>
        /// <param name="rect1">The first rectangle to compare.</param>
        /// <param name="rect2">The second rectangle to compare.</param>
        public static bool operator !=(Rect rect1, Rect rect2)
        {
            return !(rect1 == rect2);
        }
        /// <summary>Indicates whether the specified rectangles are equal. </summary>
        /// <returns>true if the rectangles have the same <see cref="P:System.Windows.Rect.Location" /> and <see cref="P:System.Windows.Rect.Size" /> values; otherwise, false.</returns>
        /// <param name="rect1">The first rectangle to compare.</param>
        /// <param name="rect2">The second rectangle to compare.</param>
        public static bool Equals(Rect rect1, Rect rect2)
        {
            if (rect1.IsEmpty)
            {
                return rect2.IsEmpty;
            }
            return rect1.X.Equals(rect2.X) && rect1.Y.Equals(rect2.Y) && rect1.Width.Equals(rect2.Width) && rect1.Height.Equals(rect2.Height);
        }
        /// <summary>Indicates whether the specified object is equal to the current rectangle.</summary>
        /// <returns>true if <paramref name="o" /> is a <see cref="T:System.Windows.Rect" /> and has the same <see cref="P:System.Windows.Rect.Location" /> and <see cref="P:System.Windows.Rect.Size" /> values as the current rectangle; otherwise, false.</returns>
        /// <param name="o">The object to compare to the current rectangle.</param>
        public override bool Equals(object o)
        {
            if (o == null || !(o is Rect))
            {
                return false;
            }
            Rect rect = (Rect)o;
            return Rect.Equals(this, rect);
        }
        /// <summary>Indicates whether the specified rectangle is equal to the current rectangle. </summary>
        /// <returns>true if the specified rectangle has the same <see cref="P:System.Windows.Rect.Location" /> and <see cref="P:System.Windows.Rect.Size" /> values as the current rectangle; otherwise, false.</returns>
        /// <param name="value">The rectangle to compare to the current rectangle.</param>
        public bool Equals(Rect value)
        {
            return Rect.Equals(this, value);
        }
        /// <summary>Creates a hash code for the rectangle. </summary>
        /// <returns>A hash code for the current <see cref="T:System.Windows.Rect" /> structure.</returns>
        public override int GetHashCode()
        {
            if (this.IsEmpty)
            {
                return 0;
            }
            return this.X.GetHashCode() ^ this.Y.GetHashCode() ^ this.Width.GetHashCode() ^ this.Height.GetHashCode();
        }
        /// <summary>Creates a new rectangle from the specified string representation. </summary>
        /// <returns>The resulting rectangle.</returns>
        /// <param name="source">The string representation of the rectangle, in the form "x, y, width, height".</param>
        public static Rect Parse(string source)
        {
            TokenizerHelper tokenizerHelper = new TokenizerHelper(source, CultureInfo.InvariantCulture);
            string text = tokenizerHelper.NextTokenRequired();
            Rect empty;
            if (text == "Empty")
            {
                empty = Rect.Empty;
            }
            else
            {
                empty = new Rect(Convert.ToDouble(text, CultureInfo.InvariantCulture), Convert.ToDouble(tokenizerHelper.NextTokenRequired(), CultureInfo.InvariantCulture), Convert.ToDouble(tokenizerHelper.NextTokenRequired(), CultureInfo.InvariantCulture), Convert.ToDouble(tokenizerHelper.NextTokenRequired(), CultureInfo.InvariantCulture));
            }
            tokenizerHelper.LastTokenRequired();
            return empty;
        }
        /// <summary>Returns a string representation of the rectangle. </summary>
        /// <returns>A string representation of the current rectangle. The string has the following form: "<see cref="P:System.Windows.Rect.X" />,<see cref="P:System.Windows.Rect.Y" />,<see cref="P:System.Windows.Rect.Width" />,<see cref="P:System.Windows.Rect.Height" />".</returns>
        public override string ToString()
        {
            return this.ConvertToString(null, null);
        }
        /// <summary>Returns a string representation of the rectangle by using the specified format provider. </summary>
        /// <returns>A string representation of the current rectangle that is determined by the specified format provider.</returns>
        /// <param name="provider">Culture-specific formatting information.</param>
        public string ToString(IFormatProvider provider)
        {
            return this.ConvertToString(null, provider);
        }
        string IFormattable.ToString(string format, IFormatProvider provider)
        {
            return this.ConvertToString(format, provider);
        }
        internal string ConvertToString(string format, IFormatProvider provider)
        {
            if (this.IsEmpty)
            {
                return "Empty";
            }
            char numericListSeparator = TokenizerHelper.GetNumericListSeparator(provider);
            return string.Format(provider, string.Concat(new string[]
            {
                "{1:", 
                format, 
                "}{0}{2:", 
                format, 
                "}{0}{3:", 
                format, 
                "}{0}{4:", 
                format, 
                "}"
            }), new object[]
            {
                numericListSeparator, 
                this._x, 
                this._y, 
                this._width, 
                this._height
            });
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Rect" /> structure that has the specified top-left corner location and the specified width and height. </summary>
        /// <param name="location">A point that specifies the location of the top-left corner of the rectangle.</param>
        /// <param name="size">A <see cref="T:System.Windows.Size" /> structure that specifies the width and height of the rectangle.</param>
        public Rect(Point location, Size size)
        {
            if (size.IsEmpty)
            {
                this = Rect.s_empty;
                return;
            }
            this._x = location._x;
            this._y = location._y;
            this._width = size._width;
            this._height = size._height;
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Rect" /> structure that has the specified x-coordinate, y-coordinate, width, and height. </summary>
        /// <param name="x">The x-coordinate of the top-left corner of the rectangle.</param>
        /// <param name="y">The y-coordinate of the top-left corner of the rectangle.</param>
        /// <param name="width">The width of the rectangle.</param>
        /// <param name="height">The height of the rectangle.</param>
        /// <exception cref="T:System.ArgumentException">
        ///   <paramref name="width" /> is a negative value.-or-<paramref name="height" /> is a negative value.</exception>
        public Rect(double x, double y, double width, double height)
        {
            if (width < 0.0 || height < 0.0)
            {
                throw new ArgumentException("WidthAndHeightCannotBeNegative");
            }
            this._x = x;
            this._y = y;
            this._width = width;
            this._height = height;
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Rect" /> structure that is exactly large enough to contain the two specified points. </summary>
        /// <param name="point1">The first point that the new rectangle must contain.</param>
        /// <param name="point2">The second point that the new rectangle must contain.</param>
        public Rect(Point point1, Point point2)
        {
            this._x = Math.Min(point1._x, point2._x);
            this._y = Math.Min(point1._y, point2._y);
            this._width = Math.Max(Math.Max(point1._x, point2._x) - this._x, 0.0);
            this._height = Math.Max(Math.Max(point1._y, point2._y) - this._y, 0.0);
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Rect" /> structure that is exactly large enough to contain the specified point and the sum of the specified point and the specified vector. </summary>
        /// <param name="point">The first point the rectangle must contain.</param>
        /// <param name="vector">The amount to offset the specified point. The resulting rectangle will be exactly large enough to contain both points.</param>
        public Rect(Point point, Vector vector)
        {
            this = new Rect(point, point + vector);
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Rect" /> structure that is of the specified size and is located at (0,0).  </summary>
        /// <param name="size">A <see cref="T:System.Windows.Size" /> structure that specifies the width and height of the rectangle.</param>
        public Rect(Size size)
        {
            if (size.IsEmpty)
            {
                this = Rect.s_empty;
                return;
            }
            this._x = (this._y = 0.0);
            this._width = size.Width;
            this._height = size.Height;
        }
        /// <summary>Indicates whether the rectangle contains the specified point.</summary>
        /// <returns>true if the rectangle contains the specified point; otherwise, false.</returns>
        /// <param name="point">The point to check.</param>
        public bool Contains(Point point)
        {
            return this.Contains(point._x, point._y);
        }
        /// <summary>Indicates whether the rectangle contains the specified x-coordinate and y-coordinate. </summary>
        /// <returns>true if (<paramref name="x" />, <paramref name="y" />) is contained by the rectangle; otherwise, false.</returns>
        /// <param name="x">The x-coordinate of the point to check.</param>
        /// <param name="y">The y-coordinate of the point to check.</param>
        public bool Contains(double x, double y)
        {
            return !this.IsEmpty && this.ContainsInternal(x, y);
        }
        /// <summary>Indicates whether the rectangle contains the specified rectangle. </summary>
        /// <returns>true if <paramref name="rect" /> is entirely contained by the rectangle; otherwise, false.</returns>
        /// <param name="rect">The rectangle to check.</param>
        public bool Contains(Rect rect)
        {
            return !this.IsEmpty && !rect.IsEmpty && (this._x <= rect._x && this._y <= rect._y && this._x + this._width >= rect._x + rect._width) && this._y + this._height >= rect._y + rect._height;
        }
        /// <summary>Indicates whether the specified rectangle intersects with the current rectangle. </summary>
        /// <returns>true if the specified rectangle intersects with the current rectangle; otherwise, false.</returns>
        /// <param name="rect">The rectangle to check.</param>
        public bool IntersectsWith(Rect rect)
        {
            return !this.IsEmpty && !rect.IsEmpty && (rect.Left <= this.Right && rect.Right >= this.Left && rect.Top <= this.Bottom) && rect.Bottom >= this.Top;
        }
        /// <summary>Finds the intersection of the current rectangle and the specified rectangle, and stores the result as the current rectangle. </summary>
        /// <param name="rect">The rectangle to intersect with the current rectangle.</param>
        public void Intersect(Rect rect)
        {
            if (!this.IntersectsWith(rect))
            {
                this = Rect.Empty;
                return;
            }
            double num = Math.Max(this.Left, rect.Left);
            double num2 = Math.Max(this.Top, rect.Top);
            this._width = Math.Max(Math.Min(this.Right, rect.Right) - num, 0.0);
            this._height = Math.Max(Math.Min(this.Bottom, rect.Bottom) - num2, 0.0);
            this._x = num;
            this._y = num2;
        }
        /// <summary>Returns the intersection of the specified rectangles. </summary>
        /// <returns>The intersection of the two rectangles, or <see cref="P:System.Windows.Rect.Empty" /> if no intersection exists.</returns>
        /// <param name="rect1">The first rectangle to compare.</param>
        /// <param name="rect2">The second rectangle to compare.</param>
        public static Rect Intersect(Rect rect1, Rect rect2)
        {
            rect1.Intersect(rect2);
            return rect1;
        }
        /// <summary>Expands the current rectangle exactly enough to contain the specified rectangle. </summary>
        /// <param name="rect">The rectangle to include.</param>
        public void Union(Rect rect)
        {
            if (this.IsEmpty)
            {
                this = rect;
                return;
            }
            if (!rect.IsEmpty)
            {
                double num = Math.Min(this.Left, rect.Left);
                double num2 = Math.Min(this.Top, rect.Top);
                if (rect.Width == double.PositiveInfinity || this.Width == double.PositiveInfinity)
                {
                    this._width = double.PositiveInfinity;
                }
                else
                {
                    double num3 = Math.Max(this.Right, rect.Right);
                    this._width = Math.Max(num3 - num, 0.0);
                }
                if (rect.Height == double.PositiveInfinity || this.Height == double.PositiveInfinity)
                {
                    this._height = double.PositiveInfinity;
                }
                else
                {
                    double num4 = Math.Max(this.Bottom, rect.Bottom);
                    this._height = Math.Max(num4 - num2, 0.0);
                }
                this._x = num;
                this._y = num2;
            }
        }
        /// <summary>Creates a rectangle that is exactly large enough to contain the two specified rectangles. </summary>
        /// <returns>The resulting rectangle.</returns>
        /// <param name="rect1">The first rectangle to include.</param>
        /// <param name="rect2">The second rectangle to include.</param>
        public static Rect Union(Rect rect1, Rect rect2)
        {
            rect1.Union(rect2);
            return rect1;
        }
        /// <summary>Expands the current rectangle exactly enough to contain the specified point. </summary>
        /// <param name="point">The point to include.</param>
        public void Union(Point point)
        {
            this.Union(new Rect(point, point));
        }
        /// <summary>Creates a rectangle that is exactly large enough to include the specified rectangle and the specified point. </summary>
        /// <returns>A rectangle that is exactly large enough to contain the specified rectangle and the specified point.</returns>
        /// <param name="rect">The rectangle to include.</param>
        /// <param name="point">The point to include.</param>
        public static Rect Union(Rect rect, Point point)
        {
            rect.Union(new Rect(point, point));
            return rect;
        }
        /// <summary>Moves the rectangle by the specified vector. </summary>
        /// <param name="offsetVector">A vector that specifies the horizontal and vertical amounts to move the rectangle.</param>
        /// <exception cref="T:System.InvalidOperationException">This method is called on the <see cref="P:System.Windows.Rect.Empty" /> rectangle.</exception>
        public void Offset(Vector offsetVector)
        {
            if (this.IsEmpty)
            {
                throw new InvalidOperationException("CannotCallMethod");
            }
            this._x += offsetVector._x;
            this._y += offsetVector._y;
        }
        /// <summary>Moves the rectangle by the specified horizontal and vertical amounts. </summary>
        /// <param name="offsetX">The amount to move the rectangle horizontally.</param>
        /// <param name="offsetY">The amount to move the rectangle vertically.</param>
        /// <exception cref="T:System.InvalidOperationException">This method is called on the <see cref="P:System.Windows.Rect.Empty" /> rectangle.</exception>
        public void Offset(double offsetX, double offsetY)
        {
            if (this.IsEmpty)
            {
                throw new InvalidOperationException("CannotCallMethod");
            }
            this._x += offsetX;
            this._y += offsetY;
        }
        /// <summary>Returns a rectangle that is offset from the specified rectangle by using the specified vector. </summary>
        /// <returns>The resulting rectangle.</returns>
        /// <param name="rect">The original rectangle.</param>
        /// <param name="offsetVector">A vector that specifies the horizontal and vertical offsets for the new rectangle.</param>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <paramref name="rect" /> is <see cref="P:System.Windows.Rect.Empty" />.</exception>
        public static Rect Offset(Rect rect, Vector offsetVector)
        {
            rect.Offset(offsetVector.X, offsetVector.Y);
            return rect;
        }
        /// <summary>Returns a rectangle that is offset from the specified rectangle by using the specified horizontal and vertical amounts. </summary>
        /// <returns>The resulting rectangle.</returns>
        /// <param name="rect">The rectangle to move.</param>
        /// <param name="offsetX">The horizontal offset for the new rectangle.</param>
        /// <param name="offsetY">The vertical offset for the new rectangle.</param>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <paramref name="rect" /> is <see cref="P:System.Windows.Rect.Empty" />.</exception>
        public static Rect Offset(Rect rect, double offsetX, double offsetY)
        {
            rect.Offset(offsetX, offsetY);
            return rect;
        }
        /// <summary>Expands the rectangle by using the specified <see cref="T:System.Windows.Size" />, in all directions. </summary>
        /// <param name="size">Specifies the amount to expand the rectangle. The <see cref="T:System.Windows.Size" /> structure's <see cref="P:System.Windows.Size.Width" /> property specifies the amount to increase the rectangle's <see cref="P:System.Windows.Rect.Left" /> and <see cref="P:System.Windows.Rect.Right" /> properties. The <see cref="T:System.Windows.Size" /> structure's <see cref="P:System.Windows.Size.Height" /> property specifies the amount to increase the rectangle's <see cref="P:System.Windows.Rect.Top" /> and <see cref="P:System.Windows.Rect.Bottom" /> properties. </param>
        /// <exception cref="T:System.InvalidOperationException">This method is called on the <see cref="P:System.Windows.Rect.Empty" /> rectangle.</exception>
        public void Inflate(Size size)
        {
            this.Inflate(size._width, size._height);
        }
        /// <summary>Expands or shrinks the rectangle by using the specified width and height amounts, in all directions. </summary>
        /// <param name="width">The amount by which to expand or shrink the left and right sides of the rectangle.</param>
        /// <param name="height">The amount by which to expand or shrink the top and bottom sides of the rectangle.</param>
        /// <exception cref="T:System.InvalidOperationException">This method is called on the <see cref="P:System.Windows.Rect.Empty" /> rectangle.</exception>
        public void Inflate(double width, double height)
        {
            if (this.IsEmpty)
            {
                throw new InvalidOperationException("CannotCallMethod");
            }
            this._x -= width;
            this._y -= height;
            this._width += width;
            this._width += width;
            this._height += height;
            this._height += height;
            if (this._width < 0.0 || this._height < 0.0)
            {
                this = Rect.s_empty;
            }
        }
        /// <summary>Returns the rectangle that results from expanding the specified rectangle by the specified <see cref="T:System.Windows.Size" />, in all directions. </summary>
        /// <returns>The resulting rectangle.</returns>
        /// <param name="rect">The <see cref="T:System.Windows.Rect" /> structure to modify.</param>
        /// <param name="size">Specifies the amount to expand the rectangle. The <see cref="T:System.Windows.Size" /> structure's <see cref="P:System.Windows.Size.Width" /> property specifies the amount to increase the rectangle's <see cref="P:System.Windows.Rect.Left" /> and <see cref="P:System.Windows.Rect.Right" /> properties. The <see cref="T:System.Windows.Size" /> structure's <see cref="P:System.Windows.Size.Height" /> property specifies the amount to increase the rectangle's <see cref="P:System.Windows.Rect.Top" /> and <see cref="P:System.Windows.Rect.Bottom" /> properties.</param>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <paramref name="rect" /> is an <see cref="P:System.Windows.Rect.Empty" /> rectangle.</exception>
        public static Rect Inflate(Rect rect, Size size)
        {
            rect.Inflate(size._width, size._height);
            return rect;
        }
        /// <summary>Creates a rectangle that results from expanding or shrinking the specified rectangle by the specified width and height amounts, in all directions. </summary>
        /// <returns>The resulting rectangle. </returns>
        /// <param name="rect">The <see cref="T:System.Windows.Rect" /> structure to modify.</param>
        /// <param name="width">The amount by which to expand or shrink the left and right sides of the rectangle.</param>
        /// <param name="height">The amount by which to expand or shrink the top and bottom sides of the rectangle.</param>
        /// <exception cref="T:System.InvalidOperationException">
        ///   <paramref name="rect" /> is an <see cref="P:System.Windows.Rect.Empty" /> rectangle.</exception>
        public static Rect Inflate(Rect rect, double width, double height)
        {
            rect.Inflate(width, height);
            return rect;
        }
        /// <summary>Returns the rectangle that results from applying the specified matrix to the specified rectangle. </summary>
        /// <returns>The rectangle that results from the operation.</returns>
        /// <param name="rect">A rectangle that is the basis for the transformation.</param>
        /// <param name="matrix">A matrix that specifies the transformation to apply.</param>
        public static Rect Transform(Rect rect, Matrix matrix)
        {
            MatrixUtil.TransformRect(ref rect, ref matrix);
            return rect;
        }
        /// <summary>Transforms the rectangle by applying the specified matrix. </summary>
        /// <param name="matrix">A matrix that specifies the transformation to apply.</param>
        public void Transform(Matrix matrix)
        {
            MatrixUtil.TransformRect(ref this, ref matrix);
        }
        /// <summary>Multiplies the size of the current rectangle by the specified x and y values.</summary>
        /// <param name="scaleX">The scale factor in the x-direction.</param>
        /// <param name="scaleY">The scale factor in the y-direction.</param>
        public void Scale(double scaleX, double scaleY)
        {
            if (this.IsEmpty)
            {
                return;
            }
            this._x *= scaleX;
            this._y *= scaleY;
            this._width *= scaleX;
            this._height *= scaleY;
            if (scaleX < 0.0)
            {
                this._x += this._width;
                this._width *= -1.0;
            }
            if (scaleY < 0.0)
            {
                this._y += this._height;
                this._height *= -1.0;
            }
        }
        private bool ContainsInternal(double x, double y)
        {
            return x >= this._x && x - this._width <= this._x && y >= this._y && y - this._height <= this._y;
        }
        private static Rect CreateEmptyRect()
        {
            return new Rect
            {
                _x = double.PositiveInfinity,
                _y = double.PositiveInfinity,
                _width = double.NegativeInfinity,
                _height = double.NegativeInfinity
            };
        }
    }
}
